package DSMini;

import miniAES.assembly;
import miniAES.enCry;

public class sevenMAES {
    public static void main(String[] args) {
        //为了便于进行，这里直接将除了区分器外的密钥全置为0
        byte [][] subKey={
                {0,0,0,0},
                {0,0,0,0},
                {0b0101,0b0000,0b1110,0b1011},
                {0b1000,0b0001,0b1111,0b1101},
                {0b0101,0b0000,0b0101,0b1011},
                {0b0111,0b1100,0b1010,0b1111},
                {0,0,0,0},//这个就作为WK5
                {1,0,0,0}
        };
        byte[][] P=new byte[16][4];
        byte[][] C=new byte[16][4];
        for (byte K00 = 0; K00 < 16; K00++) {
            //跟据猜测的密钥K00得到区分器0--15对应的XM-1[0]，数组XM0[i]中i的索引为区分器变量部分对应的值
            byte[] XM0=new byte[16];
            for (byte dfInput = 0; dfInput < 16; dfInput++) {
                XM0[dfInput]= (byte) (dfInput^K00);
            }

            for (int K_1 = 0; K_1 < 256; K_1++) {
                //得到K_1[0]和K_1[3] K_13||K_10
                byte K_10= (byte) (K_1&0b1111);
                byte K_13= (byte) (K_1>>4&0b1111);
                //向前猜测K_-1[0] [3]密钥得到对应的明文
                for (int i = 0; i < 16; i++) {
                    //从区分器输入的0到15依次得到P，索引为区分器输入的值
                    byte[] tempXM=new byte[4];//默认tempXM[1]为0进行处理
                    tempXM[0]=XM0[i];
                    byte[] mixColumn=new byte[4];
                    assembly.mixColumn(tempXM,mixColumn);//MC
                    assembly.shiftRow(mixColumn);//SR
                    assembly.nibbleInSub(mixColumn);//InSbox
                    P[i][0]= (byte) (mixColumn[0]^K_10);
                    P[i][3]= (byte) (mixColumn[3]^K_13);
                }

                //根据明文得到对应的密文
                for (int i = 0; i < 16; i++) {
                    C[i]=sevenEnCry(P[i],subKey);
                }

                //猜测K6和WK5的部分密钥比特位得到区分器的输出
                for (int bhindKey = 0; bhindKey < 4096; bhindKey++) {
                    //分解得到K_60||K_63||WK50
                    byte K_60= (byte) (bhindKey&0b1111);
                    byte K_63= (byte) (bhindKey>>4&0b1111);
                    byte WK50= (byte) (bhindKey>>8&0b1111);

                    //密文的复制提
                    byte[][] copyC=new byte[16][4];
                    for (int i = 0; i < 16; i++) {
                        copyC[i][0]=C[i][0];
                        copyC[i][1]=C[i][1];
                        copyC[i][2]=C[i][2];
                        copyC[i][3]=C[i][3];
                    }

                    //得到输出区分器的内容
                    byte[] X4=new byte[15];
                    byte X40 = 0;//为区分器输入为0时，区分器输出存放的值
                    for (int i = 0; i < 16; i++) {
                        copyC[i][0]^=K_60;
                        copyC[i][3]^=K_63;
                        assembly.shiftRow(copyC[i]);//S
                        assembly.nibbleInSub(copyC[i]);
                        byte[] mixColumn=new byte[4];
                        assembly.mixColumn(copyC[i],mixColumn);//MC
                        mixColumn[0]^=WK50;//WK5
                        assembly.shiftRow(mixColumn);//S
                        assembly.nibbleInSub(mixColumn);
                        if (i==0){
                            X40=mixColumn[0];
                        }else {
                            X4[i-1]= (byte) (X40^mixColumn[0]);
                        }
                    }
                    //进行区分器的区分
                    Boolean aBoolean = isFourMAES.discriminator(X4);
                    if (aBoolean){
                        System.out.println("K00:"+K00+","+"K_10:"+K_10+","+"K_13:"+K_13+","+"K_60:"+K_60+","+"K_63:"+K_63+","+"WK50:"+WK50);
                        return;
                    }else {
                        System.out.println(K_60);
                    }
                }

            }

        }


    }

    //得到7轮的加密结果
    public static byte[] sevenEnCry(byte[] M, byte[][] subKey){
        //密钥白化
        assembly.keyAddition(M,subKey[0]);
        //1到5轮的加密
        for (int i = 1; i <= 5; i++) {
            M= enCry.oneEnCry(M,subKey[i]);
        }
        //第6轮的处理
        byte[] mixColumnOutput =new byte[4];
        assembly.nibbleSub(M);//S盒
        assembly.shiftRow(M);//行移位
        assembly.keyAddition(M,subKey[6]);//密钥加
        assembly.mixColumn(M,mixColumnOutput);//列混淆
        //第7轮的处理
        enCry.noMixColumnCry(mixColumnOutput,subKey[7]);

        return mixColumnOutput;
    }

}




